package com.example.smartwaterapi.common.exception;

import com.example.smartwaterapi.common.api.ErrorCode;
import com.example.smartwaterapi.common.api.RestApiResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.resource.NoResourceFoundException;

import java.sql.SQLException;

/**
 * 全局异常处理
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理静态资源未找到异常（主要处理favicon.ico等静态资源）
     */
    @ExceptionHandler(NoResourceFoundException.class)
    public void handleNoResourceFoundException(NoResourceFoundException e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();

        // 忽略favicon.ico和其他常见静态资源的错误日志，避免日志污染
        if (requestURI.contains("favicon.ico") ||
                requestURI.contains(".css") ||
                requestURI.contains(".js") ||
                requestURI.contains(".png") ||
                requestURI.contains(".jpg") ||
                requestURI.contains(".gif")) {
            // 静默处理，不记录日志
            return;
        }

        // 其他资源未找到的情况才记录日志
        log.warn("请求的静态资源不存在: {}", requestURI);
    }

    /**
     * 处理业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public RestApiResponse<Object> handleBusinessException(BusinessException e, HttpServletRequest request) {
        log.warn("业务异常：{}", e.getMessage());
        return RestApiResponse.businessError(e.getCode(), e.getMessage(), e.getData())
                .path(request.getRequestURI());
    }

    /**
     * 处理API异常
     */
    @ExceptionHandler(ApiException.class)
    public RestApiResponse<Object> handleApiException(ApiException e, HttpServletRequest request) {
        log.warn("API异常：{}", e.getMessage());
        String errorCode = e.getErrorCode() != null ? String.valueOf(e.getErrorCode().getCode()) : "500";
        String errorMessage = e.getMessage() != null ? e.getMessage() : "API调用异常";
        return RestApiResponse.businessError(errorCode, errorMessage)
                .path(request.getRequestURI());
    }

    /**
     * 处理验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public RestApiResponse<Object> handleValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getDefaultMessage();
            }
        }
        log.warn("参数验证失败：{}", message);
        return RestApiResponse.badRequest(message != null ? message : "参数验证失败")
                .path(request.getRequestURI());
    }

    /**
     * 处理绑定异常
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public RestApiResponse<Object> handleBindException(BindException e, HttpServletRequest request) {
        BindingResult bindingResult = e.getBindingResult();
        String message = null;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                message = fieldError.getDefaultMessage();
            }
        }
        log.warn("参数绑定失败：{}", message);
        return RestApiResponse.badRequest(message != null ? message : "参数绑定失败")
                .path(request.getRequestURI());
    }

    /**
     * 处理请求参数缺失异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public RestApiResponse<Object> handleMissingServletRequestParameterException(MissingServletRequestParameterException e, HttpServletRequest request) {
        log.warn("缺少请求参数：{}", e.getMessage());
        return RestApiResponse.badRequest("缺少请求参数：" + e.getParameterName())
                .path(request.getRequestURI());
    }

    /**
     * 处理参数类型不匹配异常
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public RestApiResponse<Object> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
        log.warn("参数类型不匹配：{}", e.getMessage());
        return RestApiResponse.badRequest("参数类型不匹配：" + e.getName())
                .path(request.getRequestURI());
    }

    /**
     * 处理请求方法不支持异常
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    public RestApiResponse<Object> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, HttpServletRequest request) {
        log.warn("不支持的请求方法：{}", e.getMessage());
        return RestApiResponse.custom(HttpStatus.METHOD_NOT_ALLOWED, "405", "不支持的请求方法：" + e.getMethod(), null)
                .path(request.getRequestURI());
    }

    /**
     * 处理资源不存在异常（API接口不存在）
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public RestApiResponse<Object> handleNoHandlerFoundException(NoHandlerFoundException e, HttpServletRequest request) {
        log.warn("请求的API接口不存在：{}", e.getMessage());
        return RestApiResponse.notFound("请求的API接口不存在")
                .path(request.getRequestURI());
    }

    /**
     * 处理数据库异常
     */
    @ExceptionHandler(SQLException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestApiResponse<Object> handleSQLException(SQLException e, HttpServletRequest request) {
        log.error("数据库异常：", e);
        return RestApiResponse.error("数据库操作异常")
                .path(request.getRequestURI());
    }

    /**
     * 处理未知异常
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestApiResponse<Object> handleException(Exception e, HttpServletRequest request) {
        String requestURI = request.getRequestURI();

        // 忽略favicon.ico等静态资源和文件查看接口相关的异常，避免日志污染
        if (requestURI.contains("favicon.ico") ||
                requestURI.contains(".css") ||
                requestURI.contains(".js") ||
                requestURI.contains(".png") ||
                requestURI.contains(".jpg") ||
                requestURI.contains(".gif") ||
                requestURI.contains("/api/files/view/")) {
            // 静默处理，不记录日志，也不返回错误响应
            return null;
        }

        log.error("未知异常：", e);
        return RestApiResponse.error("系统异常，请联系管理员")
                .path(request.getRequestURI());
    }
}
